// 创建监听器实例
export function createListenerObject(options, isTask, prefix) {
    const listenerObj = Object.create(null);
    listenerObj.event = options.event;
    isTask && (listenerObj.id = options.id); // 任务监听器特有的 id 字段
    switch (options.listenerType) {
        case "expressionListener":
            listenerObj.expression = options.expression;
            break;
        case "delegateExpressionListener":
            listenerObj.delegateExpression = options.delegateExpression;
            break;
        default:
            listenerObj.class = options.class;
    }
    // 注入字段
    if (options.fields) {
        listenerObj.fields = options.fields.map(field => {
            return createFieldObject(field, prefix);
        });
    }
    // 任务监听器的 定时器 设置
    if (isTask && options.event === "timeout" && !!options.eventDefinitionType) {
        const timeDefinition = window.bpmnInstances.moddle.create("bpmn:FormalExpression", {
            body: options.eventTimeDefinitions
        });
        const TimerEventDefinition = window.bpmnInstances.moddle.create("bpmn:TimerEventDefinition", {
            id: `TimerEventDefinition_${uuid(8)}`,
            [`time${options.eventDefinitionType.replace(/^\S/, s => s.toUpperCase())}`]: timeDefinition
        });
        listenerObj.eventDefinitions = [TimerEventDefinition];
    }
    return window.bpmnInstances.moddle.create(`${prefix}:${isTask ? "TaskListener" : "ExecutionListener"}`, listenerObj);
}

// 创建 监听器的注入字段 实例
export function createFieldObject(option, prefix) {
    const {name, fieldType, string, expression} = option;
    const fieldConfig = fieldType === "string" ? {name, string} : {name, expression};
    return window.bpmnInstances.moddle.create(`${prefix}:Field`, fieldConfig);
}

// 更新元素扩展属性
export function updateElementExtensions(element, extensionList) {
    const extensions = window.bpmnInstances.moddle.create("bpmn:ExtensionElements", {
        values: extensionList
    });
    window.bpmnInstances.modeling.updateProperties(element, {
        extensionElements: extensions
    });
}

// 创建一个id
export function uuid(length = 8, chars) {
    let result = "";
    let charsString = chars || "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    for (let i = length; i > 0; --i) {
        result += charsString[Math.floor(Math.random() * charsString.length)];
    }
    return result;
}

/**
 * 更新基础信息
 * @param element   元素
 * @param key   字段
 * @param value     值
 */
export function updateBaseInfo(element, key, value) {
    let elementList = Array.isArray(element) ? element : [element];
    elementList.forEach(element => {
        const attrObj = Object.create(null);
        attrObj[key] = value;
        window.bpmnInstances.modeling.updateProperties(element, attrObj);
    });
}

/**
 * 更新用户任务节点按钮
 *
 * @param element   元素集合
 * @param buttons   按钮
 * @param prefix    前缀
 */
export function addOrUpdateUserTaskButton(element, buttons = [], prefix) {
    if (buttons && buttons.length > 0 && element) {
        let userTaskElementList = Array.isArray(element) ? element : [element];
        // 筛选出所有用户任务节点
        userTaskElementList = userTaskElementList.filter(el => el.type === "bpmn:UserTask");
        userTaskElementList.forEach(userTaskElement => {
            let extensionElements = userTaskElement.businessObject?.extensionElements || window.bpmnInstances.moddle.create('bpmn:ExtensionElements', {values: []});
            buttons.forEach(btn => {
                let button = extensionElements.values.find(e => e.$type === `${prefix}:Button` && e.prop === btn.code);
                if (button) {
                    button.label = btn.name;
                    button.prop = btn.code;
                    button.display = btn.display;
                } else {
                    button = window.bpmnInstances.moddle.create(`${prefix}:Button`, {
                        label: btn.name,
                        prop: btn.code,
                        display: btn.display
                    });
                    extensionElements.values.push(button);
                }
            });
            window.bpmnInstances.modeling.updateProperties(userTaskElement, {extensionElements: extensionElements});
        });
    }
}

/**
 * 删除用户任务所有按钮
 * @param element 元素
 * @param prefix 前缀
 */
export function deleteUserTaskAllButton(element, prefix) {
    if (element) {
        let userTaskElementList = Array.isArray(element) ? element : [element];
        // 筛选出所有用户任务节点
        userTaskElementList = userTaskElementList.filter(el => el.type === "bpmn:UserTask");
        userTaskElementList.forEach(userTaskElement => {
            let extensionElements = userTaskElement.businessObject?.extensionElements || window.bpmnInstances.moddle.create('bpmn:ExtensionElements', {values: []});
            let elements = extensionElements.values;
            let length = elements.length;
            while (length--) {
                if (elements[length].$type === `${prefix}:Button`) {
                    elements.splice(length, 1);
                }
            }
            window.bpmnInstances.modeling.updateProperties(userTaskElement, {extensionElements: extensionElements});
        });
    }
}

/**
 * 添加或修改用户任务表单字段
 * @param element
 * @param fields
 * @param prefix
 */
export function addOrUpdateAllFormProperty(element, fields = [], prefix) {
    if (fields && fields.length > 0 && element) {
        let userTaskElementList = Array.isArray(element) ? element : [element];
        // 筛选出所有用户任务节点
        userTaskElementList = userTaskElementList.filter(el => el.type === "bpmn:UserTask" || el.type === "bpmn:StartEvent");
        userTaskElementList.forEach(userTaskElement => {
            let extensionElements = userTaskElement.businessObject?.extensionElements || window.bpmnInstances.moddle.create('bpmn:ExtensionElements', {values: []});
            fields.forEach(formP => {
                let formProperty = extensionElements.values.find(e => e.$type === `${prefix}:FormProperty` && e.id === formP.prop);
                if (formProperty) {
                    formProperty.name = formP.name;
                    formProperty.readable = formP.readable;
                    formProperty.writable = formP.writable;
                    formProperty.required = formP.required;
                } else {
                    formProperty = window.bpmnInstances.moddle.create(`${prefix}:FormProperty`, {
                        id: formP.prop,
                        name: formP.name,
                        readable: formP.readable,
                        writable: formP.writable,
                        required: formP.required
                    });
                    extensionElements.values.push(formProperty);
                }
            });
            window.bpmnInstances.modeling.updateProperties(userTaskElement, {extensionElements: extensionElements});
        });
    }
}

/**
 * 删除用户任务所有表单字段
 * @param element 元素
 * @param prefix 前缀
 */
export function deleteAllFormProperty(element, prefix) {
    if (element) {
        let userTaskElementList = Array.isArray(element) ? element : [element];
        // 筛选出所有用户任务节点
        userTaskElementList = userTaskElementList.filter(el => el.type === "bpmn:UserTask" || el.type === "bpmn:StartEvent");
        userTaskElementList.forEach(userTaskElement => {
            let extensionElements = userTaskElement.businessObject?.extensionElements || window.bpmnInstances.moddle.create('bpmn:ExtensionElements', {values: []});
            let elements = extensionElements.values;
            let length = elements.length;
            while (length--) {
                if (elements[length].$type === `${prefix}:FormProperty`) {
                    elements.splice(length, 1);
                }
            }
            window.bpmnInstances.modeling.updateProperties(userTaskElement, {extensionElements: extensionElements});
        });
    }
}

/**
 * 查找指定节点前面的指定类型节点
 * @param elementId 节点id或节点对象
 * @param elementType 指定节点类型
 * @return {*[]}
 */
export function findPreviousNodes(elementId, elementType = ["bpmn:StartEvent", "bpmn:UserTask"]) {
    const elementRegistry = window.bpmnInstances.elementRegistry;
    const element = typeof (elementId) === 'object' ? elementId : elementRegistry.get(elementId);
    // 存储前面的所有节点
    const previousNodes = [];
    // 递归查找前面的节点
    const findPrevious = (node) => {
        node.incoming.forEach((flow) => {
            const source = flow.source;
            // 检查节点是否已经在 previousNodes 数组中
            if (!previousNodes.includes(source)) {
                if (elementType.includes(source.type)) {
                    previousNodes.push(source);
                }
                // 递归查找更早的节点
                findPrevious(source);
            }
        });
    };
    // 开始查找前面的节点
    findPrevious(element);
    return previousNodes;
}

/**
 * 对象深拷贝
 */
export const deepClone = data => {
    let type = getObjType(data);
    let obj;
    if (type === 'array') {
        obj = [];
    } else if (type === 'object') {
        obj = {};
    } else {
        //不再具有下一层次
        return data;
    }
    if (type === 'array') {
        for (var i = 0, len = data.length; i < len; i++) {
            obj.push(deepClone(data[i]));
        }
    } else if (type === 'object') {
        for (var key in data) {
            obj[key] = deepClone(data[key]);
        }
    }
    return obj;
};

export const getObjType = obj => {
    const toString = Object.prototype.toString;
    const map = {
        '[object Boolean]': 'boolean',
        '[object Number]': 'number',
        '[object String]': 'string',
        '[object Function]': 'function',
        '[object Array]': 'array',
        '[object Date]': 'date',
        '[object RegExp]': 'regExp',
        '[object Undefined]': 'undefined',
        '[object Null]': 'null',
        '[object Object]': 'object'
    };
    if (obj instanceof Element) {
        return 'element';
    }
    return map[toString.call(obj)];
};
